﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DemoPiano
{
    using Microsoft.Research.Kinect;
    using Microsoft.Research.Kinect.Nui;

    using KINECTUtility;

    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private Runtime runtime;
        private AreaChecker areaChecker;
        private readonly double windowHeight = 480;
        private readonly double windowWidth = 640;
        private readonly double unitWidht = 40;

        private List<Rectangle> markRectangles = new List<Rectangle>();
  //      private Dictionary<int, MediaElement> soundMap = new Dictionary<int, MediaElement>();

        public MainWindow()
        {
            InitializeComponent();

            areaChecker = new AreaChecker(windowWidth, windowHeight, unitWidht, unitWidht);
            areaChecker.RegistCheckJointID(JointID.HandRight);
            areaChecker.HoldTime = TimeSpan.FromMilliseconds(1200);

         //   areaChecker.AreaPushed += new AreaChecker.AreaCheckerPushEventHandler(areaChecker_AreaPushed);
            areaChecker.AreaMoved += new AreaChecker.AreaCheckerUpdateEventHandler(areaChecker_AreaMoved);
            areaChecker.AreaHold += new AreaChecker.AreaCheckerHoldEventHandler(areaChecker_AreaHold);
            buildPicture(5);
    
            runtime = new Runtime();
            runtime.Initialize(RuntimeOptions.UseColor | RuntimeOptions.UseSkeletalTracking);

            runtime.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);

            runtime.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(runtime_VideoFrameReady);
            runtime.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(runtime_SkeletonFrameReady); ;
        }

        void areaChecker_AreaHold(AreaCheckerHoldEventArgs e)
        {
            tbHand.Text = String.Format("({0},{1})", e.HoldIndexHorizontal, e.HoldIndexVertical);
            if (JointID.HandRight == e.HoldJoint)
            {
                if (soundPlayStatus.ContainsKey(e.HoldIndex))
                {
                    var mp = soundPlayStatus[e.HoldIndex].Player;
                    mp.Position = TimeSpan.FromSeconds(0);
                    mp.Play();
                    tbSound.Text = soundPlayStatus[e.HoldIndex].Key;
                }
            }
        }

        void areaChecker_AreaMoved(AreaCheckerUpdateEventArgs e)
        {
            tbHand.Text = String.Format("({0},{1})", e.CurrentIndexHorizontal, e.CurrentIndexVertical);
        }

        private Dictionary<int, SoundPlayer> soundPlayStatus = new Dictionary<int, SoundPlayer>();
        void areaChecker_AreaPushed(AreaCheckerPushEventArgs e)
        {
            if (JointID.HandRight == e.PushJoint)
            {
                if (soundPlayStatus.ContainsKey(e.PushIndex))
                {
                    var sps = this.soundPlayStatus[e.PushIndex];
                    if (!soundPlayStatus[e.PushIndex].IsPlaying)
                    {
                        sps.Player.Position = TimeSpan.FromSeconds(0);
                        sps.Player.Play();
                        tbSound.Text = soundPlayStatus[e.PushIndex].Key;
                        soundPlayStatus[e.PushIndex].IsPlaying = true;
                    }
                }
            }
        }

        private bool tracking = false;
        void runtime_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            if (tracking)
            {
                tbTrackState.Text = "Tracking";
            }
            else
            {
                tbTrackState.Text = "Lost";
            }
            tracking = false;
            var frame = e.SkeletonFrame;
            foreach (var data in frame.Skeletons)
            {
                if (data.TrackingState == SkeletonTrackingState.Tracked)
                {
                    tracking = true;
                    areaChecker.BeginCheck();
                    areaChecker.IsIncludePoint(data.Joints[JointID.HandRight].Position.X, data.Joints[JointID.HandRight].Position.Y, JointID.HandRight, z:data.Joints[JointID.HandRight].Position.Z);
                    areaChecker.EndCheck();
                    break;
                }
            }
        }

        void runtime_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
        {
            PlanarImage image = e.ImageFrame.Image;
            videoFrameImage.Source = BitmapImage.Create(image.Width, image.Height
                , 96, 96, PixelFormats.Bgr32, null, image.Bits, image.Width * image.BytesPerPixel);
        }

        List<MediaElement> GetOrderedSounds()
        {
            var sounds = new List<MediaElement>();
            sounds.Add(soundC);
            sounds.Add(soundD);
            sounds.Add(soundE);
            sounds.Add(soundF);
            sounds.Add(soundG);
            sounds.Add(soundA);
            sounds.Add(soundB);
            return sounds;
        }
        List<String> GetOrderdSoundTexts()
        {
            var texts = new List<String>();
            texts.Add("C");
            texts.Add("D");
            texts.Add("E");
            texts.Add("F");
            texts.Add("G");
            texts.Add("A");
            texts.Add("B");
            return texts;
        }

        void buildPicture(int indexV)
        {
            var sounds = GetOrderedSounds();
            var soundTexts=GetOrderdSoundTexts();
            
            for (int h = 0; h < 7; h++)
            {
                int indexH = 1 + 2 * h;
                var rectangle = new Rectangle();
                rectangle.Width = unitWidht;
                rectangle.Height = unitWidht;
                rectangle.Fill = new SolidColorBrush(Colors.Azure);
                rectangle.Opacity = 0.5;

                int? index = areaChecker.GetAreaIndex(indexV, indexH);
                soundPlayStatus.Add(index.Value, new SoundPlayer(index.Value, sounds[h]) { Key = soundTexts[h] });

                markRectangles.Add(rectangle);
                Canvas.SetTop(rectangle, indexV * unitWidht);
                Canvas.SetLeft(rectangle, indexH * unitWidht);
                ARCanvas.Children.Add(rectangle);
            }
        }
    }

    class SoundPlayer
    {
        public int Index { get; set; }
        public string Key { get; set; }
        public MediaElement Player { get; set; }
        public bool IsPlaying { get; set; }

        public SoundPlayer(int index, MediaElement mp)
        {
            Index = index;
            Player = mp;
            IsPlaying = false;
            Player.MediaEnded += new RoutedEventHandler(Player_MediaEnded);
        }

        void Player_MediaEnded(object sender, EventArgs e)
        {
            IsPlaying = false;
        }
    }
}
